{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c51a8d17",
   "metadata": {},
   "source": [
    "## 易错点\n",
    "1. data = data[data['userID'].isin(counts[counts >= 50].index)] 后面要index\n",
    "2. data = data[data['userID'].isin(counts[counts>=50].index)] 是>= 如果是则无数据\n",
    "3. ratings_matrix[row[5],row[4]] = row[1] ,两个坐标合起来写放一个中括号里,其中行号是row[0]\n",
    "4. artists_rated = np.where(ratings_matrix[i]>0)[0] 后面有[0] 这个地方有时忘记有时搞错,忘了+2\n",
    "5. 矩阵获取通过[]\n",
    "6. similar_users = np.argsort(-user_similarity[user_index])[1:] 忘了加2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e2ba1ef5",
   "metadata": {},
   "outputs": [],
   "source": [
    "#导入pandas和numpy 库\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "# 读取数据集\n",
    "user_artists = pd.read_csv('./data/music/user_artists.dat',sep='\\t')\n",
    "artists = pd.read_csv('./data/music/artists.dat', sep='\\t', usecols=['id','name'])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "668d30bf",
   "metadata": {},
   "source": [
    "1.将user_artists和artists两个DataFrame进行合并，以user_artists中的artistID和artists中的id为键值进行连接。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ce1f0688",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 合并数据集\n",
    "#此处由考生填写(单行)\n",
    "data = pd.merge(user_artists,artists,left_on='artistID',right_on='id')\n",
    "#此处由考生填写(单行)\n",
    "data = data.drop(['id','artistID'],axis=1)# 删除data 中的id 和artistlD列\n",
    "data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e471463",
   "metadata": {},
   "source": [
    "2.去除评分次数少于50次的音乐和用户。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "32121f42",
   "metadata": {},
   "outputs": [],
   "source": [
    "counts = data['userID'].value_counts()#计算每个用户的评分次数\n",
    "#此处由考生填写\n",
    "data = data[data['userID'].isin(counts[counts >= 50].index)]\n",
    "#此处由考生填写\n",
    "counts = data['name'].value_counts() #计算每个音乐的评分次数\n",
    "#此处由考生填写\n",
    "data = data[data['name'].isin(counts[counts >= 50].index)]\n",
    "#此处由考生填写"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "e567f7c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 转换成数值才能计算相似度分数\n",
    "# enumerate enumerate是一个内置函数，用于将一个可遍历的数据对象（如列表、元组、字符串等）组合为一个索引序列，同时列出数据下标和数据本身‌\n",
    "#将音乐和用户ID 转换为数字\n",
    "name_to_index={}#创建 name_to_index 字典\n",
    "index_to_name={}#创建 index_to_name 字典\n",
    "for i,name in enumerate(data['name'].unique()): \n",
    "    #遍历data中的 name 列\n",
    "    name_to_index[name]=i#将name 映射到数字\n",
    "    index_to_name[i]=name #将数字映射到 name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "783fae2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "user_id_to_index={}#创建 user_id_to_index 字典\n",
    "index_to_user_id={}#创建 index_to_user_id 字典\n",
    "for i,user_id in enumerate(data['userID'].unique()):\n",
    "    #追历data 中的 userID 列\n",
    "    user_id_to_index[user_id]=i#将user_id 映射到数字\n",
    "    index_to_user_id[i]=user_id #将数字映射到user_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "5aa8d617",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 增加两列\n",
    "data['name_index']= data['name'].apply(lambda x:name_to_index[x])#将data中的name映射到数字\n",
    "data['user_index']= data['userID'].apply(lambda x:user_id_to_index[x])#将data中的userID映射到数字\n",
    "#构建用户-音乐评分矩阵\n",
    "n_users=len(user_id_to_index)#获取用户数量\n",
    "n_artists=len(name_to_index)#获取音乐数量\n",
    "ratings_matrix=np.zeros((n_users,n_artists))#创建用户-音乐评分矩阵"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bf117f4",
   "metadata": {},
   "source": [
    "3、将 data 中的评分填入用户-音乐评分炬阵，使得ratingsmatrix的输出为:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "f1da945b",
   "metadata": {},
   "outputs": [],
   "source": [
    "for row in data.itertuples(): # 遍历data\n",
    "    #此处由考生填写\n",
    "    ratings_matrix[row[5],row[4]] = row[1]\n",
    "    #此处由考生填写\n",
    "from sklearn.metrics.pairwise import cosine_similarity #导入 sklearn 库中的余弦相例度计算函敬\n",
    "#计算用户之同的相似度\n",
    "user_similarity=cosine_similarity(ratings_matrix)#计算用户之间的相似度#为用户推荐音乐"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "466319c1",
   "metadata": {},
   "source": [
    "4.获取与用户最相似的用户索引 similar_users(不包括自己)，使得 similar_users 的输出为:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "805ddf71",
   "metadata": {},
   "outputs": [],
   "source": [
    "user_index=0#设置用户索引\n",
    "#此处由考生填写\n",
    "similar_users = np.argsort(-user_similarity[user_index])[1:]\n",
    "#此处由考生填写\n",
    "recommended_artists=[]#创建推荐音乐列表"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e3ab0d4",
   "metadata": {},
   "source": [
    "5.填补以下程序，获取相似用户评分的音乐索引artists_rated。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "422f0538",
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in similar_users:#遍历相似用户索引\n",
    "    #此处由考生填写\n",
    "    artist_rated = np.where(ratings_matrix[i]>0)[0]\n",
    "    #此处由考生填写\n",
    "    for j in artist_rated:#遍历音乐索引\n",
    "        if ratings_matrix[user_index][j] == 0:#用户未评分\n",
    "            recommended_artists.append((j,ratings_matrix[i][j]))# 将音乐加入推荐音乐列表\n",
    "recommended_artists = sorted(recommended_artists, key=lambda x: x[1],reverse=True)[:10]#筛选出推荐音乐中的前10首\n",
    "for artist in recommended_artists:#遍历推荐音乐\n",
    "    print(artists[artists['name']== index_to_name[artist [0]]]['name'].values[0])\n",
    "#打印推荐音乐"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b52fc39e",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "PySpark-2.4.5",
   "language": "python",
   "name": "pyspark-2.4.5"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
